package com.lry.sso.client.filter;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.lry.sso.auth.common.bean.RequestInfoContext;
import com.lry.sso.auth.common.constant.LoginAuthorizationConstant;
import com.lry.sso.auth.common.exception.AuthException;
import com.lry.sso.auth.common.util.HttpUtils;
import com.lry.sso.auth.common.util.SessionInfo;
import com.lry.sso.common.entity.response.Ret;
import com.lry.sso.service.redis.service.RedisService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * 检查会话是否有效，暂时不做局部会话和全局会话
 *
 * @author 李瑞益
 * @date 2020-02-13 10:45
 */
@Component
@WebFilter(urlPatterns = "/*")
@Order(Ordered.HIGHEST_PRECEDENCE)
@ConditionalOnProperty(name = "sso.auth.redisFilter.enable",havingValue = "true")
public class AuthClientRedisFilter implements Filter {

    private static final Logger logger = LoggerFactory.getLogger(AuthClientRedisFilter.class);

    @Autowired
    private RedisService redisService;

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest req = (HttpServletRequest)request;
        HttpServletResponse res =(HttpServletResponse)response;
        logger.info("请求验证是否登录。。。");
        String sessionId = this.getSessionKey(req, LoginAuthorizationConstant.SESSION_ID_KEY);

        if (sessionId == null) {
            logger.info("无sessionId");
            HttpUtils.writeResponse(res, HttpStatus.UNAUTHORIZED.value(), JSON.toJSONString(Ret.error(AuthException.AUTH_FAIL)));
            return;
        }
        logger.info("从cookie中获取的sessionId :{}",sessionId);

        String sessionInfoStr = redisService.get(sessionId);
        if (sessionInfoStr == null) {
            logger.info("无session信息（登录信息）");
            HttpUtils.writeResponse(res, HttpStatus.UNAUTHORIZED.value(), JSON.toJSONString(Ret.error(AuthException.AUTH_FAIL)));
            return;
        }
        SessionInfo sessionInfo = null;
        try {
            sessionInfo = JSON.parseObject(sessionInfoStr, new TypeReference<SessionInfo>() {
            });
            logger.info("登录信息：{}",sessionInfo);
            RequestInfoContext.set(sessionInfo);
        } catch (Exception e) {
            logger.info("token（登录信息）无效");
            HttpUtils.writeResponse(res, HttpStatus.UNAUTHORIZED.value(),JSON.toJSONString(Ret.error(AuthException.AUTH_FAIL)));
            return;
        }
        if (sessionInfo == null) {
            logger.info("无session信息（登录信息）");
            HttpUtils.writeResponse(res, HttpStatus.UNAUTHORIZED.value(), JSON.toJSONString(Ret.error(AuthException.AUTH_FAIL)));
            return;
        }

        RequestInfoContext.set(sessionInfo);
        chain.doFilter(request,response);
    }

    /**
     * 获取cookie中的sessionId
     * @param request 请求
     * @param cookieName cookie保存的key
     * @return cookie保存的sessionId
     */
    private String getSessionKey(HttpServletRequest request,String cookieName) {
        Cookie[] cookies = request.getCookies();
        if (cookies == null) {
            logger.warn("获取到的cookie为null");
            return null;
        }
        for (Cookie cookie : cookies) {
            if (cookie.getName().equals(cookieName)) {
                return cookie.getValue();
            }
        }
        return null;
    }
}
